home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / Capture / DVApp / CDVGraph.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  53.2 KB  |  1,219 lines

  1. // ---------------------------------------------------------------------------
  2. // File: CDVGraph.cpp
  3. // 
  4. // Desc: CDVGraph Class definition, it supports DV Graph Building
  5. //       This is the class to build all AVC graphs using 
  6. //       MSTape.sys
  7. //      
  8. // Copyright (c) 2000-2001, Microsoft Corporation. All rights reserved.
  9. //----------------------------------------------------------------------------
  10.  
  11. #include <windows.h>
  12. #include <tchar.h>
  13. #include <mmreg.h>
  14. #include <streams.h>
  15. #include <xprtdefs.h> 
  16. #include <atlbase.h>
  17. #include <atlconv.h>
  18. #include "CDVGraph.h"
  19. #include "dbgsup.h"
  20.  
  21. /*-----------------------------------------------------------------------------
  22. |   Function:   CDVGraph::CDVGraph
  23. |   Purpose:    Constructor for digital tv graph class.  
  24. |   Arguments:  None 
  25. |   Returns:    None 
  26. |   Notes:      initializes the digital tv graph components
  27. \----------------------------------------------------------------------------*/
  28. CDVGraph::CDVGraph(void)
  29. : m_VideoFormat( DVENCODERVIDEOFORMAT_NTSC )
  30. , m_DVResolution( DVRESOLUTION_HALF )
  31. , m_SubunitMode ( VcrMode )
  32. , m_pGraph( NULL )
  33. , m_pCaptureGraphBuilder( NULL )
  34. , m_pMediaControl( NULL )
  35. , m_pMediaEvent( NULL )
  36. , m_pInputFileFilter (NULL )
  37. , m_pVideoWindow( NULL )
  38. , m_pDeviceFilter( NULL )
  39. , m_pIAMExtDevice( NULL )
  40. , m_pIAMExtTransport( NULL )
  41. , m_pIAMTCReader( NULL )
  42. , m_pDroppedFrames( NULL )
  43. {
  44. }
  45.  
  46. /*-----------------------------------------------------------------------------
  47. |   Function:   CDVGraph::~CDVGraph
  48. |   Purpose:    Destructor for the graph info class.  
  49. |   Arguments:  None
  50. |   Returns:    None 
  51. |   Notes:      Any clean up needed should be put here.
  52. \----------------------------------------------------------------------------*/
  53. CDVGraph::~CDVGraph(void)
  54. {
  55.     if(m_pVideoWindow != NULL)
  56.     {
  57.         //Otherwise, a video image remains on the screen and the user cannot get rid of it. 
  58.         m_pVideoWindow->put_Visible(OAFALSE);
  59.  
  60.         //Otherwise, messages are sent to the wrong window, likely causing errors.
  61.         m_pVideoWindow->put_Owner(NULL);  
  62.     }
  63.  
  64.     FreeFilters();
  65. }
  66.  
  67. /*-----------------------------------------------------------------------------
  68. |   Function:   CDVGraph::FreeFilters
  69. |   Purpose:    Destructor for the graph info class.  
  70. |   Arguments:  None
  71. |   Returns:    None 
  72. |   Notes:      Any clean up needed should be put here.
  73. \----------------------------------------------------------------------------*/
  74. void CDVGraph::FreeFilters()
  75. {
  76.     // releases the dshow interfaces created 
  77.     SAFE_RELEASE(m_pGraph) 
  78.     SAFE_RELEASE(m_pCaptureGraphBuilder) 
  79.     SAFE_RELEASE(m_pMediaEvent);
  80.     SAFE_RELEASE(m_pMediaControl) 
  81.     SAFE_RELEASE(m_pInputFileFilter);
  82.     SAFE_RELEASE(m_pDeviceFilter);
  83.     SAFE_RELEASE(m_pIAMExtDevice);
  84.     SAFE_RELEASE(m_pIAMExtTransport);
  85.     SAFE_RELEASE(m_pIAMTCReader);
  86.     SAFE_RELEASE(m_pVideoWindow);
  87.     SAFE_RELEASE(m_pDroppedFrames);
  88. }
  89.  
  90. /*-----------------------------------------------------------------------------
  91. |   Function:   CAVCGraph::GraphInitialize
  92. |   Purpose:    Initializing the graph class members.  
  93. |   Arguments:  None
  94. |   Returns:    Boolean TRUE if successfull or throws exception detailing the error
  95. |   Notes:      Initializes the required DirectShow interfaces
  96. \----------------------------------------------------------------------------*/
  97. HRESULT CDVGraph::InitializeGraph()
  98. {
  99.     HRESULT hr = S_OK;
  100.     Dump1( TEXT(" CDVGraph::InitializeGraph().hr = %#x"), hr );
  101.  
  102.  
  103.     //All DirectShow FilterGraphs need this
  104.     hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (LPVOID *)&m_pGraph );
  105.     CHECK_ERROR( TEXT(" Failed to create FilterGraph."), hr);
  106.  
  107.     // Helps the building all Graphs
  108.     hr = CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2, (void **)&m_pCaptureGraphBuilder);
  109.     CHECK_ERROR( TEXT(" Failed to create CaptureGraphBuilder2."), hr);
  110.  
  111.     hr = m_pCaptureGraphBuilder->SetFiltergraph(m_pGraph);
  112.     CHECK_ERROR( TEXT(" Failed to SetFiltergraph."), hr);
  113.  
  114.     hr = m_pGraph->QueryInterface(IID_IMediaEventEx, reinterpret_cast<PVOID *>(&m_pMediaEvent)); 
  115.     CHECK_ERROR( TEXT(" Failed to QI IMediaEventEx."), hr);
  116.  
  117.     // DShow Interface for Run, Stop, Pause the flow of the streams through the filter graph
  118.     hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) & m_pMediaControl);
  119.     CHECK_ERROR( TEXT(" Failed to QI IMediaControl."), hr);
  120.  
  121.     hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void **)&m_pVideoWindow);
  122.     CHECK_ERROR( TEXT(" Failed to  QI IVideoWindow."), hr);
  123.  
  124.     return hr;
  125. }
  126.  
  127. /*-----------------------------------------------------------------------------
  128. |   Function:   CDVGraph::BuildBasicGraph
  129. |   Purpose:    Add device filter to the graph 
  130. |   Arguments:  None 
  131. |   Returns:    HRESULT
  132. |   Notes:      
  133. \----------------------------------------------------------------------------*/
  134. HRESULT CDVGraph::BuildBasicGraph()
  135. {
  136.     HRESULT hr;
  137.  
  138.     hr = InitializeGraph();
  139.     CHECK_ERROR( TEXT(" Failed to  initialize graph."), hr);
  140.  
  141.     hr = AddDeviceFilter();
  142.     CHECK_ERROR( TEXT(" Failed to  add device filter."), hr);
  143.  
  144.     ASSERT(m_pDeviceFilter);
  145.  
  146.     hr = m_pDeviceFilter->QueryInterface(IID_IAMExtTransport, (void **) &m_pIAMExtTransport);
  147.     CHECK_ERROR( TEXT(" Failed to  QI IAMExtTransport."), hr);
  148.   
  149.     hr = m_pDeviceFilter->QueryInterface(IID_IAMExtDevice, (void **) &m_pIAMExtDevice);
  150.     CHECK_ERROR( TEXT(" Failed to  QI IAMExtDevice."), hr);
  151.  
  152.     hr = m_pDeviceFilter->QueryInterface(IID_IAMTimecodeReader, (void **) &m_pIAMTCReader);
  153.     CHECK_ERROR( TEXT(" Failed to  QI IAMTimecodeReader."), hr);
  154.  
  155.     hr= GetDVMode( &m_SubunitMode );
  156.     CHECK_ERROR( TEXT(" GetMode Failed."), hr);
  157.  
  158.     return S_OK;
  159. }
  160.  
  161. /*-----------------------------------------------------------------------------
  162. |   Function:   CDVGraph::AddDeviceFilter
  163. |   Purpose:    Load (not add) a filter of the name "Microsoft DV Camera and VCR" 
  164. |               which connects to the specified filter
  165. |   Arguments:  None 
  166. |   Returns:    HRESULT
  167. |   Notes:      This method adds the device filter to the filtergraph
  168. \----------------------------------------------------------------------------*/
  169. HRESULT CDVGraph::AddDeviceFilter()
  170. {
  171.     HRESULT hr = S_OK;
  172.     ICreateDevEnum*     pCreateDevEnum = NULL;
  173.     IEnumMoniker *      pEnumMoniker = NULL;
  174.     IMoniker *          pMoniker = NULL;
  175.     ULONG               nFetched = 0;
  176.  
  177.     // Create Device Enumerator
  178.     hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<PVOID *>(&pCreateDevEnum));
  179.     CHECK_ERROR( TEXT(" Failed to create SystemDeviceEnum."), hr);
  180.     
  181.     // Create the enumerator of the monikers for the specified Device Class & reset them 
  182.     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
  183.     if(SUCCEEDED(hr) && pEnumMoniker)
  184.         pEnumMoniker->Reset();
  185.     else   {
  186.         Dump( TEXT(" Failed to CreateClassEnumerator.") );
  187.         return hr;
  188.     }
  189.  
  190.     // Loop through to the last moniker
  191.     while(SUCCEEDED(pEnumMoniker->Next( 1, &pMoniker, &nFetched )) && pMoniker)    
  192.     {
  193.         IPropertyBag *pPropBag;
  194.         hr = pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void **)&pPropBag );
  195.         CHECK_ERROR( TEXT(" Failed to BindToStorage."), hr);
  196.  
  197.         //Friendly name
  198.         VARIANT varFriendlyName;
  199.         varFriendlyName.vt = VT_BSTR;
  200.         hr = pPropBag->Read( L"FriendlyName", &varFriendlyName, 0 );
  201.         CHECK_ERROR( TEXT(" Failed to read friendlyname."), hr);
  202.       
  203. #ifdef UNICODE
  204.         wcscpy(m_DeviceName, varFriendlyName.bstrVal);
  205. #else
  206.         WideCharToMultiByte( CP_ACP, 0, varFriendlyName.bstrVal, -1, m_DeviceName, sizeof(m_DeviceName), 0, 0 );    
  207. #endif
  208.         VariantClear( &varFriendlyName );
  209.         
  210.         if(!lstrcmp(TEXT("Microsoft DV Camera and VCR"), m_DeviceName))
  211.         {
  212.             hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pDeviceFilter );
  213.             CHECK_ERROR( TEXT(" Failed to BindToObject."), hr);
  214.  
  215.             hr = m_pGraph->AddFilter(m_pDeviceFilter, L"Filter");
  216.             CHECK_ERROR( TEXT(" Failed to AddFilter."), hr);
  217.  
  218.             SAFE_RELEASE(pPropBag );
  219.             SAFE_RELEASE(pMoniker);
  220.             break;
  221.         }
  222.         else
  223.             hr = E_FAIL;
  224.  
  225.         SAFE_RELEASE(pPropBag );
  226.         SAFE_RELEASE(pMoniker);
  227.     }//end of while
  228.  
  229.     SAFE_RELEASE( pEnumMoniker );
  230.     SAFE_RELEASE( pCreateDevEnum );
  231.     return hr;
  232. }
  233.  
  234. /*-------------------------------------------------------------------------
  235. Routine:        CDVGraph::GetTapeInfo
  236. Purpose:        Get Frame rate and availability of dvcr tape
  237. Arguments:    None
  238. Returns:        HRESULT as appropriate
  239. Notes:          
  240. ------------------------------------------------------------------------*/
  241. HRESULT CDVGraph::GetTapeInfo(void)
  242. {
  243.     HRESULT hr;
  244.     LONG    lMediaType = 0;
  245.     LONG    lInSignalMode = 0;
  246.  
  247.     // Query Media Type of the transport
  248.     hr = m_pIAMExtTransport->GetStatus(ED_MEDIA_TYPE, &lMediaType);
  249.     CHECK_ERROR( TEXT(" GetStatus failed."), hr);
  250.  
  251.     if (ED_MEDIA_NOT_PRESENT == lMediaType)
  252.     {
  253.         //we want to return failure if there is no tape installed
  254.         hr = S_FALSE;  
  255.     } 
  256.     else
  257.     {
  258.         //tape type should always be DVC
  259.         ASSERT(ED_MEDIA_DVC == lMediaType);
  260.  
  261.         // Now lets query for the signal mode of the tape.
  262.         hr = m_pIAMExtTransport->GetTransportBasicParameters(ED_TRANSBASIC_INPUT_SIGNAL, &lInSignalMode, NULL);
  263.         CHECK_ERROR( TEXT(" GetTransportBasicParameters failed."), hr);
  264.  
  265.         // determine whether the camcorder supports ntsc or pal
  266.         switch (lInSignalMode)
  267.         {
  268.             case ED_TRANSBASIC_SIGNAL_525_60_SD :
  269.                 m_AvgTimePerFrame = 33;  // 33 milli-sec (29.97 FPS)
  270.                 m_VideoFormat = DVENCODERVIDEOFORMAT_NTSC;
  271.                 break;
  272.  
  273.             case ED_TRANSBASIC_SIGNAL_525_60_SDL :
  274.                 m_AvgTimePerFrame = 33;  // 33 milli-sec (29.97 FPS)
  275.                 m_VideoFormat = DVENCODERVIDEOFORMAT_NTSC;
  276.                 break;
  277.  
  278.             case ED_TRANSBASIC_SIGNAL_625_50_SD :
  279.                 m_AvgTimePerFrame = 40;  // 40 milli-sec (25FPS)
  280.                 m_VideoFormat = DVENCODERVIDEOFORMAT_PAL;
  281.                 break;
  282.  
  283.             case ED_TRANSBASIC_SIGNAL_625_50_SDL :
  284.                 m_AvgTimePerFrame = 40;  // 40 milli-sec (25FPS)
  285.                 m_VideoFormat = DVENCODERVIDEOFORMAT_PAL;
  286.                 break;
  287.  
  288.             default : 
  289.                 Dump(TEXT("Unsupported or unrecognized tape format type"));
  290.                 m_AvgTimePerFrame = 33;  // 33 milli-sec (29.97 FPS); default
  291.                 break;
  292.         }
  293.         Dump1(TEXT("Avg time per frame is %d FPS"), m_AvgTimePerFrame);
  294.     }
  295.  
  296.     return hr;
  297. }
  298.  
  299. /*-------------------------------------------------------------------------
  300. Routine:        CDVGraph::DV_GetDVMode
  301. Purpose:        Determines camera mode using IAMExtDevice::GetCapability()
  302. Arguments:      None
  303. Returns:        Subunit mode of camera device
  304. Notes:          
  305. ------------------------------------------------------------------------*/
  306. HRESULT CDVGraph::GetDVMode(DV_MODE *pSubunitMode)
  307. {
  308.     HRESULT hr = S_OK;
  309.     LONG    lDeviceType = 0;
  310.  
  311.     ASSERT(m_pDeviceFilter);
  312.     //  Query the Device Type Capability
  313.     hr = m_pIAMExtDevice->GetCapability(ED_DEVCAP_DEVICE_TYPE, &lDeviceType, 0);
  314.     CHECK_ERROR( TEXT(" m_pIAMExtDevice->GetCapability() failed."), hr);
  315.     
  316.     switch (lDeviceType)
  317.     {
  318.         case 0 :
  319.             //device type is unknown
  320.             *pSubunitMode = UnknownMode;
  321.             break;
  322.  
  323.         case ED_DEVTYPE_VCR :
  324.             *pSubunitMode = VcrMode;
  325.             break;
  326.  
  327.         case ED_DEVTYPE_CAMERA :
  328.             *pSubunitMode = CameraMode;
  329.             break;
  330.  
  331.         default :
  332.             Dump(TEXT("GetCapability returned an unknown device type!"));
  333.             break;
  334.     } 
  335.     
  336.     return hr;
  337.  
  338. /*-------------------------------------------------------------------------
  339. Routine:        DV_SaveGraph
  340. Purpose:        Save the filter graph into a *.grf file
  341. Arguments:    FileName
  342. Returns:        HRESULT as appropriate
  343. Notes:          
  344. ------------------------------------------------------------------------*/
  345. HRESULT CDVGraph::SaveGraphToFile(TCHAR* sGraphFile)
  346. {
  347.     IStorage *          pStorage = NULL;
  348.     IStream *           pStream = NULL;
  349.     IPersistStream *    pPersistStream = NULL;
  350.     HRESULT             hr = S_OK;
  351.  
  352.     if(m_pCaptureGraphBuilder == NULL || sGraphFile == NULL)
  353.         return E_FAIL;
  354.  
  355.     USES_CONVERSION;
  356.     // Either Open or Create the *.GRF file
  357.     hr = StgOpenStorage( T2W (sGraphFile), NULL, STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, NULL, &pStorage );
  358.     if ( STG_E_FILENOTFOUND == hr )
  359.         hr = StgCreateDocfile( T2W (sGraphFile), STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE , NULL , &pStorage);
  360.     CHECK_ERROR( TEXT(" StgCreateDocfile failed."), hr);
  361.     
  362.     hr = pStorage->CreateStream( L"ActiveMovieGraph", STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, NULL, NULL, &pStream );
  363.     CHECK_ERROR( TEXT(" CreateStream failed."), hr);
  364.  
  365.     // Persist the stream, save & commit to disk
  366.     hr = m_pGraph->QueryInterface( IID_IPersistStream, (void **) &pPersistStream );
  367.     CHECK_ERROR( TEXT(" QI IPersistStream failed."), hr);
  368.  
  369.     hr = pPersistStream->Save(pStream, TRUE);
  370.     CHECK_ERROR( TEXT(" pPersistStream->Save() failed."), hr);
  371.  
  372.     hr = pStorage->Commit( STGC_DEFAULT );
  373.     CHECK_ERROR( TEXT(" Save GRF file failed."), hr);
  374.  
  375.     SAFE_RELEASE(pStorage);
  376.     SAFE_RELEASE(pStream);
  377.     SAFE_RELEASE(pPersistStream);
  378.  
  379.     return hr;
  380. }
  381.  
  382. /*---------------------------------------------------------------------------------------------------------
  383. Routine:        CDVGraph::MakePreviewGraph()
  384. Purpose:        Builds the DV preview graph
  385. Arguments:      None
  386. Returns:        HRESULT as apropriate
  387. Notes:          This is a  preview graph for DV :           
  388.                     DV_Cam(AV Out)->DVSplitter(vid)->DVCodec->VideoWindow
  389.                                     DVSplitter(aud)->Default DirectSound device
  390. ---------------------------------------------------------------------------------------------------------*/
  391. HRESULT CDVGraph::MakePreviewGraph()
  392. {
  393.     m_iGraphType = GRAPH_PREVIEW;
  394.     HRESULT hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, m_pDeviceFilter,  NULL, NULL);
  395.     return hr;
  396. }
  397.  
  398. /*---------------------------------------------------------------------------------------------------------
  399. Routine:        CDVGraph::MakeDvToFileGraph_Type1
  400. Purpose:        Builds and runs the DV to File graph
  401. Arguments:      None
  402. Returns:        HRESULT as apropriate
  403. Notes:          This is a capture & preview graph for DV Type 1 AVI files           
  404.                     This graph is a bit more complex.  It looks like this:
  405.                     DV_Cam(AV Out)->SmartTee(capture)->AviMux->FileWriter
  406.                                     SmartTee(preview)->DVSplitter(vid)->DVCodec->VideoWindow
  407.                                                        DVSplitter(aud)->Default DirectSound device
  408. ---------------------------------------------------------------------------------------------------------*/
  409. HRESULT CDVGraph::MakeDvToFileGraph_Type1(TCHAR* OutputFileName)
  410. {
  411.     m_iGraphType = GRAPH_DV_TO_FILE;
  412.     HRESULT hr = S_OK;
  413.     USES_CONVERSION;
  414.  
  415.     ASSERT(OutputFileName[0]);
  416.  
  417.     
  418.     CComPtr<IBaseFilter>        ppf;
  419.     CComPtr<IFileSinkFilter>    pSink;     
  420.     hr = m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, T2W (OutputFileName), &ppf, &pSink);
  421.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_Type1::m_pCaptureGraphBuilder->SetOutputFileName() failed."), hr);
  422.  
  423.     hr = SetAviOptions(ppf, INTERLEAVE_NONE);
  424.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_Type1::m_pCaptureGraphBuilder->SetAviOptions() failed."), hr);
  425.     
  426.     // The graph we're making is:   MSDV --> Smart Tee --> AVI Mux --> File Writer
  427.     //                         --> DV Splitter --> DV Decoder --> Video Renderer
  428.     //                                 --> Audio Renderer       
  429.     // Connect interleaved stream of MSDV to the AVI Mux/FW
  430.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, m_pDeviceFilter, NULL, ppf);
  431.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  432.  
  433.     // Build a preview graph off of it too
  434.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, m_pDeviceFilter, NULL, NULL);
  435.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  436.    
  437.     return hr;
  438. }
  439.  
  440. /*---------------------------------------------------------------------------------------------------------
  441. Routine:        DV_MakeDvToFileGraph_NoPre
  442. Purpose:        Builds and runs the DV to File graph with no preview
  443. Arguments:      None
  444. Returns:        HRESULT as apropriate
  445. Notes:          This is a capture only graph for DV Type 1 AVI files            
  446.                     This graph is not too complex.  It looks like this:
  447.                     DV_Cam(AV Out)->AviMux->FileWriter
  448. ---------------------------------------------------------------------------------------------------------*/
  449. HRESULT CDVGraph::MakeDvToFileGraph_NoPre_Type1(TCHAR* OutputFileName)
  450. {
  451.     m_iGraphType = GRAPH_DV_TO_FILE_NOPRE;
  452.     HRESULT hr = S_OK;
  453.     USES_CONVERSION;    
  454.     ASSERT(OutputFileName[0]) ;
  455.     
  456.     //add the avimux, and file writer to the graph 
  457.     CComPtr<IBaseFilter>        ppf = NULL;
  458.     CComPtr<IFileSinkFilter>    pSink = NULL;
  459.     hr = m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, T2W(OutputFileName), &ppf, &pSink);
  460.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->SetOutputFileName() failed."), hr);
  461.  
  462.     hr = SetAviOptions(ppf, INTERLEAVE_NONE);
  463.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  464.  
  465.     // the graph we're making is:  MSDV --> AVI Mux --> File Writer
  466.     // Set the AVI Options like interleaving mode etc...       
  467.     // Build the graph
  468.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, m_pDeviceFilter, NULL, ppf);
  469.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  470.          
  471.     return hr;
  472. }
  473.  
  474. /*---------------------------------------------------------------------------------------------------------
  475. Routine:        DV_MakeFileToDvGraph
  476. Purpose:        Builds and runs the File to DV graph
  477. Arguments:    None
  478. Returns:        HRESULT as apropriate
  479. Notes:          This is a transmit & playback graph for DV Type 1 AVI files         
  480.                     This graph is a bit more complex.  It looks like this:
  481.                      FileSource->AVI_Splitter->InfPinTee->DV_Camera
  482.                                                InfPinTee->DVSplitter(vid)->DVDecoder->VideoWIndow
  483.                                                           DVSplitter(aud)->Default DirectSound device
  484. ---------------------------------------------------------------------------------------------------------*/
  485. HRESULT CDVGraph::MakeFileToDvGraph_Type1(TCHAR* InputFileName)
  486. {
  487.     m_iGraphType = GRAPH_FILE_TO_DV;
  488.     HRESULT hr = S_OK;
  489.     USES_CONVERSION;
  490.     // Add the file as source filter to the graph
  491.     hr = m_pGraph->AddSourceFilter(T2W (InputFileName ), T2W(InputFileName), &m_pInputFileFilter);
  492.     CHECK_ERROR( TEXT(" CDVGraph::MakeFileToDvGraph_Type1::m_pGraph->AddSourceFilter failed."), hr);
  493.  
  494.     CComPtr<IBaseFilter>    pAviSplitter         = NULL;
  495.     CComPtr<IBaseFilter>    pInfTee              = NULL;
  496.  
  497.     hr = CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pAviSplitter));
  498.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::CoCreate AviSplitter  failed."), hr);
  499.  
  500.     hr = CoCreateInstance(CLSID_InfTee, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pInfTee));
  501.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::CoCreate InfTee failed."), hr);
  502.  
  503.     // the graph we're making is:   Async Reader --> AVI SPlitter --> Tee --> MSDV
  504.     //                                        --> DV Splitter --> DV Decoder --> VidRend
  505.     //                                                --> AudRend
  506.     // Add the AVI Splitter
  507.     hr = m_pGraph->AddFilter(pAviSplitter, L"AVI Splitter");
  508.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pGraph->AddFilter failed."), hr);
  509.  
  510.     // Connect file source to the splitter
  511.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, pAviSplitter);
  512.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  513.  
  514.     // Add an infinite Tee
  515.     hr = m_pGraph->AddFilter(pInfTee, L"Infinite Tee"); 
  516.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pGraph->AddFilter() failed."), hr);
  517.  
  518.     // Connect the Splitter to the Tee
  519.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, &MEDIATYPE_Interleaved, pAviSplitter, NULL, pInfTee);
  520.     CHECK_ERROR( TEXT(" CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  521.  
  522.     // Connect one branch of the tee to MSDV 
  523.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pInfTee, NULL, m_pDeviceFilter);
  524.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  525.  
  526.     // Build a preview graph off the other branch
  527.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pInfTee, NULL, NULL);
  528.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  529.  
  530.     return hr;
  531. }
  532.  
  533. /*---------------------------------------------------------------------------------------------------------
  534. Routine:        DV_MakeFileToDvGraph_NoPre
  535. Purpose:        Builds and runs the File to DV graph without preview
  536. Arguments:      None
  537. Returns:        HRESULT as apropriate
  538. Notes:          This is a transmit only graph for DV Type 1 AVI files           
  539.                     This graph is a bit simplex.  It looks like this:
  540.                     FileSource->AVI_Splitter->DV_Camera
  541. ---------------------------------------------------------------------------------------------------------*/
  542. HRESULT CDVGraph::MakeFileToDvGraph_NoPre_Type1(TCHAR* InputFileName)
  543. {
  544.     m_iGraphType = GRAPH_FILE_TO_DV_NOPRE;
  545.     HRESULT hr = S_OK;
  546.     USES_CONVERSION;
  547.     ASSERT(InputFileName[0]) ;
  548.  
  549.     // Add the file as source filter to the graph
  550.     hr = m_pGraph->AddSourceFilter(T2W(InputFileName), T2W(InputFileName), &m_pInputFileFilter);
  551.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDVGraph_NoPre_Type1::m_pGraph->AddSourceFilter() failed."), hr);
  552.  
  553.     // the graph we're making is:    Async Reader --> AVI Splitter --> MSDV 
  554.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, m_pDeviceFilter);
  555.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDVGraph_NoPre_Type1::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  556.               
  557.     return hr;
  558. }
  559.  
  560. /*---------------------------------------------------------------------------------------------------------
  561. Routine:        DV_MakeDvToFileGraph_Type2
  562. Purpose:        Builds and runs the DV to File graph
  563. Arguments:    None
  564. Returns:        HRESULT as apropriate
  565. Notes:          This is a capture & preview graph for DV Type 2 AVI files           
  566.                     This graph is a bit more complex.  It looks like this:
  567.                     DV_Cam(AV Out)->DVSplitter(vid)->SmartTee(capture)->AviMux->FileWriter
  568.                                                      SmartTee(preview)->DVCodec->VideoWindow
  569.                                     DVSplitter(aud)->InfinitePinTee->AviMux->FileWriter
  570.                                                      InfinitePinTee->Default DirectSound device
  571. ---------------------------------------------------------------------------------------------------------*/
  572. HRESULT CDVGraph::MakeDvToFileGraph_Type2(TCHAR* OutputFileName)
  573. {
  574.     m_iGraphType = GRAPH_DV_TO_FILE_TYPE2;
  575.     HRESULT hr = S_OK;
  576.     USES_CONVERSION;
  577.     // making sure there is a output file selected
  578.     ASSERT(OutputFileName[0]);
  579.  
  580.     CComPtr<IBaseFilter>    pDVSplitter          = NULL;
  581.     hr = CoCreateInstance(CLSID_DVSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pDVSplitter));
  582.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::create DVSplitter failed."), hr);
  583.  
  584.     hr =  m_pGraph->AddFilter(pDVSplitter, L"DV Splitter");
  585.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::m_pGraph->AddFilter() failed."), hr);
  586.  
  587.  
  588.     //add the avimux, and file writer to the graph 
  589.     CComPtr<IBaseFilter> ppf = NULL;
  590.     CComPtr<IFileSinkFilter> pSink = NULL;
  591.     hr = m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, T2W (OutputFileName), &ppf, &pSink);
  592.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::m_pCaptureGraphBuilder->SetOutputFileName() failed."), hr);
  593.  
  594.     // Set the AVI Options like interleaving mode etc...
  595.     hr = SetAviOptions(ppf, INTERLEAVE_NONE);
  596.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::SetAviOptions() failed."), hr);
  597.              
  598.     // the graph we're making is:   MSDV --> Smart Tee --> DV SPLITTER --> AVI MUX --> File Writer
  599.     //                                 -->
  600.     //
  601.     //                                                 --> DV SPLITTER --> DV DEC --> Video Renderer
  602.     //                                 --> Audio Renderer 
  603.  
  604.     // Connect MSDV Interleave stream through DV Splitter to AVI MUX/FW
  605.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, m_pDeviceFilter, pDVSplitter, ppf);
  606.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  607.  
  608.     // Connect the other DV Splitter output to the AVI MUX/FW
  609.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pDVSplitter, NULL, ppf);
  610.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  611.  
  612.     // Render the preview part of the graph
  613.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved, m_pDeviceFilter, NULL, NULL);
  614.     CHECK_ERROR( TEXT("CDVGraph::MakeDVToFileGraph_Type2::m_pCaptureGraphBuilder->RenderStream() failed."), hr);
  615.  
  616.     return hr;
  617. }
  618.  
  619. /*---------------------------------------------------------------------------------------------------------
  620. Routine:        DV_MakeDvToFileGraph_NoPre_Type2
  621. Purpose:        Builds and runs the DV to File graph
  622. Arguments:    None
  623. Returns:        HRESULT as apropriate
  624. Notes:          This is a capture only graph for DV Type 2 AVI files            
  625.                     This graph is a bit simplex .  It looks like this:
  626.                     DV_Cam(AV Out)->DVSplitter(vid)->AviMux->FileWriter
  627.                                                 DVSplitter(aud)->AviMux->FileWriter
  628. ---------------------------------------------------------------------------------------------------------*/
  629. HRESULT CDVGraph::MakeDvToFileGraph_NoPre_Type2(TCHAR* OutputFileName)
  630. {
  631.     m_iGraphType = GRAPH_DV_TO_FILE_NOPRE_TYPE2;
  632.     HRESULT hr = S_OK;
  633.     USES_CONVERSION;
  634.     // making sure there is a output file selected
  635.     ASSERT(OutputFileName[0]);
  636.  
  637.     CComPtr<IBaseFilter>    pDVSplitter          = NULL;
  638.  
  639.     hr = CoCreateInstance(CLSID_DVSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pDVSplitter));
  640.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::create DVSplitter failed."), hr);
  641.    
  642.     hr = m_pGraph->AddFilter(pDVSplitter, L"DV Splitter");
  643.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::m_pGraph->AddFilter failed."), hr);
  644.  
  645.     //add the avimux, and file writer to the graph 
  646.     CComPtr<IBaseFilter>        ppf = NULL;
  647.     CComPtr<IFileSinkFilter>    pSink = NULL;
  648.     hr = m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, T2W (OutputFileName), &ppf, &pSink);
  649.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::m_pCaptureGraphBuilder->SetOutputFileName failed."), hr);
  650.               
  651.     // the graph we're making is:   MSDV --> Smart Tee --> DV SPLITTER --> AVI MUX --> File Writer
  652.     //                                 --> 
  653.  
  654.     // connect MSDV interleaved pin through DV Splitter to AVI MUX/FW
  655.     hr = m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, m_pDeviceFilter, pDVSplitter, ppf);
  656.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  657.  
  658.     // connect the other DV Splitter output to the AVI MUX/FW
  659.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pDVSplitter, NULL, ppf);
  660.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  661.                       
  662.     // Set the AVI Options like interleaving mode etc...
  663.     hr = SetAviOptions(ppf, INTERLEAVE_NONE);
  664.     CHECK_ERROR( TEXT("CDVGraph::MakeDvToFileGraph_NoPre_Type2::SetAviOptions failed."), hr);
  665.  
  666.     return hr;
  667. }
  668.  
  669. /*---------------------------------------------------------------------------------------------------------
  670. Routine:        DV_MakeFileToDvGraph_Type2
  671. Purpose:        Builds and runs the File to DV graph 
  672. Arguments:    None
  673. Returns:        HRESULT as apropriate
  674. Notes:          This is a transmit & playback graph for DV Type 2 AVI files         
  675.                     This graph is a bit complex.  It looks like this:
  676.                      FileSource->AVI_Splitter(vid) ->DVMuxer(vid)---------->InfPinTee->DV_Camera
  677.                                         AVI_Splitter(aud)->DVMuxer(aud)                 InfPinTee->DVSplitter(vid)->DVDecoder->VideoWIndow
  678.                                                                                                                                             DVSplitter(aud)->DSoundDevice
  679. ---------------------------------------------------------------------------------------------------------*/
  680. HRESULT CDVGraph::MakeFileToDvGraph_Type2(TCHAR* InputFileName)
  681. {
  682.     m_iGraphType = GRAPH_FILE_TO_DV_TYPE2;
  683.     HRESULT hr = S_OK;
  684.     USES_CONVERSION;
  685.     ASSERT(InputFileName[0] );
  686.  
  687.     CComPtr<IBaseFilter>             pDVMux               = NULL;
  688.     CComPtr<IBaseFilter>             pInfTee              = NULL;
  689.     hr = CoCreateInstance(CLSID_DVMux, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pDVMux));
  690.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::create DVMux failed."), hr);
  691.  
  692.     hr = CoCreateInstance(CLSID_InfTee, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pInfTee));
  693.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::CoCreate InfTeefailed."), hr); 
  694.  
  695.     // Add the file as source filter to the graph
  696.     hr =m_pGraph->AddSourceFilter(T2W (InputFileName), T2W (InputFileName), &m_pInputFileFilter);
  697.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pGraph->AddSourceFilter failed."), hr);
  698.  
  699.     // Add the DVMuxer to the graph
  700.     hr = m_pGraph->AddFilter(pDVMux, L"DV Muxer");
  701.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pGraph->AddFilter failed."), hr);
  702.  
  703.     //Add the infinite pin tee filter to the graph and connect it downstream to the dv muxer
  704.     hr = m_pGraph->AddFilter(pInfTee, L"Infinite Tee"); 
  705.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pGraph->AddFilter failed."), hr);
  706.  
  707.     // the graph we need to build is:    ASYNC reader --> AVI SPLITTER --> DV MUX --> TEE --> MSDV
  708.     //                                 -->            --> DVSP --> DV DEC --> VR
  709.     //                                                 --> AR
  710.     // connect file source video stream to DV MUX
  711.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, pDVMux);
  712.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  713.  
  714.     // connect file source audio stream to DV MUX
  715.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, pDVMux);
  716.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  717.  
  718.     // connect DV MUX to tee
  719.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pDVMux, NULL, pInfTee);
  720.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  721.  
  722.     // connect one branch of tee to MSDV transmit
  723.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pInfTee, NULL, m_pDeviceFilter);
  724.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  725.  
  726.     // render other branch of tee to audio & video preview
  727.     CComPtr<IPin> pOut;
  728.     hr = m_pCaptureGraphBuilder->FindPin(pInfTee, PINDIR_OUTPUT, NULL, NULL, TRUE, 0, &pOut);
  729.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pCaptureGraphBuilder->FindPin failed."), hr);
  730.  
  731.     hr = m_pGraph->Render(pOut);
  732.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_Type2::m_pGraph->Render failed."), hr);
  733.  
  734.     return hr;
  735. }
  736.  
  737. /*---------------------------------------------------------------------------------------------------------
  738. Routine:        DV_MakeFileToDvGraph_NoPre_Type2
  739. Purpose:        Builds and runs the File to DV graph 
  740. Arguments:    None
  741. Returns:        HRESULT as apropriate
  742. Notes:          This is a transmit only graph for DV Type 2 AVI files           
  743.                     This graph looks like this:
  744.                      FileSource->AVI_Splitter(vid) ->DVMuxer(vid)----->DV_Camera
  745.                                         AVI_Splitter(aud)->DVMuxer(aud)                 
  746. ---------------------------------------------------------------------------------------------------------*/
  747. HRESULT CDVGraph::MakeFileToDvGraph_NoPre_Type2(TCHAR* InputFileName)
  748. {
  749.     m_iGraphType = GRAPH_FILE_TO_DV_NOPRE_TYPE2;
  750.     HRESULT hr = S_OK;
  751.     USES_CONVERSION;
  752.     ASSERT(InputFileName[0]);
  753.  
  754.     CComPtr< IBaseFilter >            pDVMux               = NULL;
  755.     hr = CoCreateInstance(CLSID_DVMux, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<PVOID *>(&pDVMux));
  756.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::CoCreate DVMux failed."), hr);
  757.   
  758.     // Add the file as source filter to the graph
  759.     hr = m_pGraph->AddSourceFilter(T2W (InputFileName), T2W (InputFileName), &m_pInputFileFilter);
  760.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::m_pGraph->AddSourceFilter failed."), hr);
  761.  
  762.     // Add the DVMuxer to the graph
  763.     hr = m_pGraph->AddFilter(pDVMux, L"DV Muxer");
  764.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::add DVMux failed."), hr);
  765.  
  766.     // the graph we need to build is:   ASYNC reader --> AVI SPLITTER --> DV MUX --> MSDV
  767.     //                                -->
  768.  
  769.     // connect file video stream to DV MUX
  770.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, pDVMux);
  771.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  772.  
  773.     // connect file audio stream to DV MUX
  774.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, m_pInputFileFilter, NULL, pDVMux);
  775.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  776.  
  777.     // connect DV MUX to DV Transmit
  778.     hr = m_pCaptureGraphBuilder->RenderStream(NULL, NULL, pDVMux, NULL, m_pDeviceFilter);
  779.     CHECK_ERROR( TEXT("CDVGraph::MakeFileToDvGraph_NoPre_Type2::m_pCaptureGraphBuilder->RenderStream failed."), hr);
  780.  
  781.     return hr;
  782. }
  783.  
  784. /*-------------------------------------------------------------------------
  785. Routine:        DV_SetAviOptions
  786. Purpose:        Routine for changing AVI Mux properties.  In this sample, we just set a few options.  
  787.                     These options could be set through the Avi Mux property sheet, or through a separate dialog
  788. Arguments:    pointer to the AVI renderer (from SetOutputFileName())
  789. Returns:        HRESULT as appropriate
  790. Notes:          
  791. ------------------------------------------------------------------------*/
  792. HRESULT CDVGraph::SetAviOptions(IBaseFilter *ppf, InterleavingMode INTERLEAVE_MODE)
  793. {
  794.     HRESULT hr;
  795.     ASSERT(ppf);
  796.     CComPtr<IConfigAviMux>          pMux           = NULL;
  797.     CComPtr<IConfigInterleaving>    pInterleaving  = NULL;
  798.  
  799.     // QI for interface AVI Muxer
  800.     hr = ppf->QueryInterface(IID_IConfigAviMux, reinterpret_cast<PVOID *>(&pMux));
  801.     CHECK_ERROR( TEXT("CDVGraph::SetAviOptions::QI IConfigAviMux failed."), hr);
  802.  
  803.     hr = pMux->SetOutputCompatibilityIndex(TRUE);
  804.     CHECK_ERROR( TEXT("CDVGraph::SetAviOptions::pMux->SetOutputCompatibilityIndex failed."), hr);
  805.  
  806.     // QI for interface Interleaving
  807.     hr = ppf->QueryInterface(IID_IConfigInterleaving, reinterpret_cast<PVOID *>(&pInterleaving));
  808.     CHECK_ERROR( TEXT("CDVGraph::SetAviOptions::QI IConfigInterleaving failed."), hr);
  809.  
  810.     // put the interleaving mode (full, none, half)
  811.     hr = pInterleaving->put_Mode(INTERLEAVE_MODE);
  812.     CHECK_ERROR( TEXT("CDVGraph::SetAviOptions::pInterleaving->put_Mode failed."), hr);
  813.    
  814.     return hr;
  815.  
  816. /*-----------------------------------------------------------------------------
  817. |   Function:   CAVCGraph::NukeFilters
  818. |   Purpose:    Tears downs the graph from the specified filter onwards.  
  819. |   Arguments:  Filter to be nuked downstream from
  820. |   Returns:    None 
  821. |   Notes:      The filter specified in the argument is not removed from the filtergraph; This is a recursively calling function
  822. \----------------------------------------------------------------------------*/
  823. HRESULT CDVGraph::NukeFilters(IBaseFilter *pFilter, BOOL bNukeDownStream)
  824. {
  825.     HRESULT hr = S_OK;
  826.     IPin *pPin = NULL, *pToPin = NULL;
  827.     IEnumPins *pEnumPins = NULL;
  828.  
  829.     ULONG uFetched = 0;
  830.     PIN_INFO PinInfo;
  831.     LONG lDelayCount = 100;
  832.  
  833.     ASSERT(m_pGraph);
  834.     
  835.     // Validating the the pointer to the Filter is not null
  836.     if(!pFilter)
  837.     {
  838.         Dump( TEXT("CAVCGraph::NukeFilters():: Invalid Argument:: Invalid filter to nuke from") );
  839.         return E_FAIL;
  840.     }
  841.  
  842.     // enumerate all the pins on this filter
  843.     // reset the enumerator to the first pin
  844.     hr = pFilter->EnumPins(&pEnumPins);
  845.     CHECK_ERROR( TEXT("CAVCGraph::NukeFilters():: Could not enumerate pins on the filter to be nuked fro."), hr);
  846.     pEnumPins->Reset(); 
  847.    
  848.     // Loop through all the pins of the filter
  849.     while( SUCCEEDED(pEnumPins->Next(1, &pPin, &uFetched)) && pPin )
  850.     {
  851.         // Get the pin & its pin_info struct that this filter's pin is connected to 
  852.         hr = pPin->ConnectedTo(&pToPin);
  853.         if(SUCCEEDED(hr) &&pToPin )
  854.         {
  855.             hr = pToPin->QueryPinInfo(&PinInfo);
  856.             CHECK_ERROR( TEXT("pToPin->QueryPinInfo failed."), hr);
  857.                    
  858.             // Check that this ConnectedTo Pin is a input pin thus validating that our filter's pin is an output pin
  859.             if(PinInfo.dir == PINDIR_INPUT && bNukeDownStream)
  860.             {
  861.                 // thus we have a pin on the downstream filter so nuke everything downstream of that filter recursively
  862.                 NukeFilters(PinInfo.pFilter, bNukeDownStream);
  863.                 // Disconnect the two pins and remove the downstream filter
  864.                 m_pGraph->Disconnect(pToPin);
  865.                 m_pGraph->Disconnect(pPin);
  866.                 //always leave the Camera filter in the graph
  867.                 if (PinInfo.pFilter != m_pDeviceFilter)
  868.                 {
  869.                     if(FAILED(m_pGraph->RemoveFilter(PinInfo.pFilter)))
  870.                     {
  871.                         Dump(TEXT("CAVCGraph::NukeFilters():: The Filter cannot be removed from the filtergraph"));
  872.                     }
  873.                 }
  874.  
  875.             }
  876.  
  877.             SAFE_RELEASE(PinInfo.pFilter);                 
  878.             SAFE_RELEASE(pToPin);
  879.             Dump(TEXT("CAVCGraph::NukeFilters():: release ToPin\n"));
  880.         }
  881.         SAFE_RELEASE(pPin);       
  882.     }
  883.  
  884.     SAFE_RELEASE(pEnumPins);
  885.     return S_OK;
  886. }
  887.  
  888. /*-------------------------------------------------------------------------
  889. Routine:        DV_StartGraph
  890. Purpose:        Starts the Filter Graph 
  891. Arguments:    None
  892. Returns:        HResult as appropriate
  893. Notes:          
  894. ------------------------------------------------------------------------*/
  895. HRESULT CDVGraph::StartGraph(void)
  896. {
  897.     HRESULT hr;
  898.  
  899.     // start the graph
  900.     hr = m_pMediaControl->Run();
  901.     if ( FAILED(hr))
  902.     {
  903.         Dump(TEXT("CDVGraph::StartGraph::m_pMediaControl->Run() Failed"));
  904.         // stop parts that ran
  905.         m_pMediaControl->Stop();
  906.     }
  907.  
  908.     return hr;
  909. }
  910.  
  911. /*-------------------------------------------------------------------------
  912. Routine:        DV_PauseGraph
  913. Purpose:        Starts the Filter Graph 
  914. Arguments:    None
  915. Returns:        HResult as appropriate
  916. Notes:          
  917. ------------------------------------------------------------------------*/
  918. HRESULT CDVGraph::PauseGraph(void)
  919. {
  920.     HRESULT hr;
  921.  
  922.     // Pause the graph
  923.     hr = m_pMediaControl->Pause();
  924.     if ( FAILED(hr))
  925.     {
  926.         Dump(TEXT("CDVGraph::StartGraph::m_pMediaControl->Pause() Failed"));
  927.          // stop parts that ran
  928.         m_pMediaControl->Stop();
  929.     }
  930.  
  931.     return hr;
  932. }
  933.  
  934.  
  935. /*-------------------------------------------------------------------------
  936. Routine:        DV_StopGraph
  937. Purpose:        Starts the Filter Graph 
  938. Arguments:    None
  939. Returns:        HResult as appropriate
  940. Notes:          
  941. ------------------------------------------------------------------------*/
  942. HRESULT CDVGraph::StopGraph(void)
  943. {
  944.  
  945.     HRESULT hr = S_OK;
  946.     hr = m_pMediaControl->Stop();
  947.  
  948.     return hr;
  949. }
  950.  
  951. /*-------------------------------------------------------------------------
  952. Routine:        CDVGraph::getDroppedFrameNum
  953. Purpose:        Callback proc to display dropped frame info
  954. Arguments:      [in]DWORD is the graph in transmit mode
  955. Arguments:      [out]long* number of dropped frames
  956. Arguments:      [out]long* number of not dropped frames
  957. Returns:        None
  958. Notes:          For both Capture & Transmit graphs
  959. ------------------------------------------------------------------------*/
  960. HRESULT CDVGraph::getDroppedFrameNum( BOOL *bIsModeTransmit, long* pDropped, long* pNotdropped)
  961. {
  962.     HRESULT hr;
  963.     CComPtr<IPin> pAVIn = NULL;
  964.  
  965.     SAFE_RELEASE(m_pDroppedFrames);
  966.  
  967.     // capture
  968.     if (GRAPH_DV_TO_FILE == m_iGraphType || GRAPH_DV_TO_FILE_NOPRE == m_iGraphType ||
  969.         GRAPH_DV_TO_FILE_TYPE2 == m_iGraphType || GRAPH_DV_TO_FILE_NOPRE_TYPE2 == m_iGraphType)
  970.         *bIsModeTransmit = FALSE;
  971.     // transmit
  972.     else if (GRAPH_FILE_TO_DV == m_iGraphType || GRAPH_FILE_TO_DV_NOPRE == m_iGraphType ||
  973.         GRAPH_FILE_TO_DV_TYPE2 == m_iGraphType || GRAPH_FILE_TO_DV_NOPRE_TYPE2 == m_iGraphType)
  974.         *bIsModeTransmit = TRUE;
  975.  
  976.     if( *bIsModeTransmit)
  977.     {
  978.         hr = m_pCaptureGraphBuilder->FindPin(m_pDeviceFilter, PINDIR_INPUT, NULL, NULL, FALSE, 0, &pAVIn);
  979.         if(FAILED(hr) || pAVIn == NULL)
  980.         {
  981.             Dump(TEXT("CDVGraph::getDroppedFrameNum::m_pCaptureGraphBuilder->FindPin Failed"));
  982.             return hr;
  983.         }
  984.         
  985.         hr = pAVIn->QueryInterface(IID_IAMDroppedFrames, reinterpret_cast<PVOID *>(&m_pDroppedFrames));
  986.         CHECK_ERROR( TEXT("CDVGraph::getDroppedFrameNum::QI IAMDroppedFrames failed."), hr);        
  987.     }
  988.     else
  989.     {
  990.         hr = m_pCaptureGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, 
  991.             &MEDIATYPE_Interleaved, m_pDeviceFilter, IID_IAMDroppedFrames, reinterpret_cast<PVOID *>(&m_pDroppedFrames));
  992.         CHECK_ERROR( TEXT("CDVGraph::getDroppedFrameNum::m_pCaptureGraphBuilder->FindInterface failed."), hr);        
  993.     }
  994.      
  995.     hr = m_pDroppedFrames->GetNumDropped(pDropped);
  996.     CHECK_ERROR( TEXT("CDVGraph::getDroppedFrameNum::m_pDroppedFrames->GetNumDropped failed."), hr);        
  997.  
  998.     hr = m_pDroppedFrames->GetNumNotDropped(pNotdropped);
  999.     CHECK_ERROR( TEXT("CDVGraph::getDroppedFrameNum::m_pDroppedFrames->GetNumDropped failed."), hr);        
  1000.  
  1001.     return hr;
  1002. }
  1003.  
  1004. /*-------------------------------------------------------------------------
  1005. Routine:        ChangeFrameRate
  1006. Purpose:        controls discard or not half of the frames in the video stream
  1007. Arguments:      none
  1008. Returns:        HRESULT
  1009. Notes:          For NTSC, the frame rate is reduced from 30 frames per second (fps) to 15 fps. 
  1010.                 For PAL, the frame rate is reduced from 25 fps to 12.5 fps.
  1011. ------------------------------------------------------------------------*/
  1012. HRESULT CDVGraph::ChangeFrameRate(BOOL bHalfFrameRate)
  1013. {
  1014.     HRESULT hr = S_OK;
  1015.     CComPtr<IBaseFilter>    pDVSplitter;
  1016.     CComPtr<IDVSplitter>    pIDVSplitter = NULL;
  1017.  
  1018.     /* Obtain the dv docoder's IBaseFilter interface. */
  1019.     hr = m_pGraph->FindFilterByName(L"DV Splitter", &pDVSplitter) ;
  1020.     CHECK_ERROR( TEXT("CDVGraph::ChangeFrameRate()::m_pGraph->FindFilterByName failed."), hr);        
  1021.  
  1022.     hr = pDVSplitter->QueryInterface(IID_IDVSplitter, reinterpret_cast<PVOID *>(&pIDVSplitter));
  1023.     CHECK_ERROR( TEXT("CDVGraph::ChangeFrameRate()::QI IDVSplitter failed."), hr);        
  1024.     
  1025.     if(bHalfFrameRate)
  1026.         hr = pIDVSplitter->DiscardAlternateVideoFrames(1);  // if the value is non-zero, discards alternate frames. 
  1027.     else 
  1028.         hr = pIDVSplitter->DiscardAlternateVideoFrames(0);  // If the value is zero, the filter delivers every frame.
  1029.     CHECK_ERROR( TEXT("CDVGraph::ChangeFrameRate()::pIDVSplitter->DiscardAlternateVideoFrames failed."), hr);        
  1030.     
  1031.     return hr;
  1032. }
  1033.  
  1034. /*-------------------------------------------------------------------------------
  1035. Routine:        CDVGraph::GetResolutionFromDVDecoderPropertyPage
  1036. Purpose:        controls discard or not half of the frames in the video stream
  1037. Arguments:      none
  1038. Returns:        HRESULT
  1039. Notes:          For NTSC, the frame rate is reduced from 30 frames per second (fps) to 15 fps. 
  1040.                 For PAL, the frame rate is reduced from 25 fps to 12.5 fps.
  1041. ---------------------------------------------------------------------------------*/
  1042. HRESULT CDVGraph::GetResolutionFromDVDecoderPropertyPage( HWND hwndApp, BOOL bChangeResolution)
  1043. {
  1044.     HRESULT hr;
  1045.     IBaseFilter *pDVDecoder;
  1046.     IIPDVDec    *pIPDVDec;
  1047.  
  1048.     /* Obtain the dv docoder's IBaseFilter interface. */
  1049.     hr = m_pGraph->FindFilterByName(L"DV Video Decoder", &pDVDecoder) ;
  1050.     CHECK_ERROR( TEXT("CDVGraph::GetResolutionFromDVDecoderPropertyPage()::m_pGraph->FindFilterByName failed."), hr);        
  1051.  
  1052.     CComPtr<ISpecifyPropertyPages> pProp;
  1053.     hr = pDVDecoder->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
  1054.     CHECK_ERROR( TEXT("CDVGraph::GetResolutionFromDVDecoderPropertyPage()::QI ISpecifyPropertyPages failed."), hr);        
  1055.     
  1056.     // Get the filter's name and IUnknown pointer.
  1057.     FILTER_INFO FilterInfo;
  1058.     hr = pDVDecoder->QueryFilterInfo(&FilterInfo); 
  1059.     CHECK_ERROR( TEXT("CDVGraph::GetResolutionFromDVDecoderPropertyPage()::pDVDecoder->QueryFilterInfo failed."), hr);        
  1060.  
  1061.     // Show the page. 
  1062.     if(bChangeResolution)
  1063.     {
  1064.         CAUUID caGUID;
  1065.         pProp->GetPages(&caGUID);
  1066.         OleCreatePropertyFrame(
  1067.             hwndApp,                // Parent window
  1068.             0, 0,                   // (Reserved)
  1069.             FilterInfo.achName,     // Caption for the dialog box
  1070.             1,                      // Number of objects (just the filter)
  1071.             (IUnknown **)&pDVDecoder,            // Array of object pointers. 
  1072.             caGUID.cElems,          // Number of property pages
  1073.             caGUID.pElems,          // Array of property page CLSIDs
  1074.             0,                      // Locale identifier
  1075.             0, NULL                 // Reserved
  1076.         );
  1077.         CoTaskMemFree(caGUID.pElems);
  1078.  
  1079.     }
  1080.  
  1081.     // Clean up.
  1082.     FilterInfo.pGraph->Release(); 
  1083.    
  1084.     hr = pDVDecoder->QueryInterface(IID_IIPDVDec, reinterpret_cast<PVOID *>(&pIPDVDec));
  1085.     CHECK_ERROR( TEXT("CDVGraph::GetResolutionFromDVDecoderPropertyPage()::QI IIPDVDec failed."), hr);        
  1086.  
  1087.     hr = pIPDVDec->get_IPDisplay(reinterpret_cast <int *>(&m_DVResolution));
  1088.     CHECK_ERROR( TEXT("CDVGraph::GetResolutionFromDVDecoderPropertyPage()::pIPDVDec->get_IPDisplay failed."), hr);        
  1089.   
  1090.     SAFE_RELEASE( pDVDecoder );
  1091.     SAFE_RELEASE( pIPDVDec );
  1092.  
  1093.     return hr;
  1094. }
  1095.  
  1096. /*-------------------------------------------------------------------------
  1097. Routine:        CDVGraph::GetResolutionFromDVDecoderPropertyPage
  1098. Purpose:        controls discard or not half of the frames in the video stream
  1099. Arguments:      none
  1100. Returns:        HRESULT
  1101. Notes:          For NTSC, the frame rate is reduced from 30 frames per second (fps) to 15 fps. 
  1102.                 For PAL, the frame rate is reduced from 25 fps to 12.5 fps.
  1103. ------------------------------------------------------------------------*/
  1104. HRESULT CDVGraph::GetVideoWindowDimensions (int* pWidth, int *pHeight, BOOL bChangeResolution,HWND hwndApp)
  1105. {
  1106.     HRESULT hr;
  1107.  
  1108.     hr = GetResolutionFromDVDecoderPropertyPage( hwndApp, bChangeResolution );
  1109.     CHECK_ERROR( TEXT("CDVGraph::GetVideoWindowDimensions()::GetResolutionFromDVDecoderPropertyPage() failed."), hr); 
  1110.  
  1111.     switch (m_DVResolution)
  1112.     {
  1113.         case DVRESOLUTION_FULL:
  1114.             *pWidth = DVENCODER_WIDTH;
  1115.             if (DVENCODERVIDEOFORMAT_PAL == m_VideoFormat)
  1116.                 *pHeight = PAL_DVENCODER_HEIGHT;
  1117.             else if (DVENCODERVIDEOFORMAT_NTSC == m_VideoFormat)
  1118.                 *pHeight = NTSC_DVENCODER_HEIGHT;
  1119.             break;
  1120.  
  1121.         case DVRESOLUTION_HALF:
  1122.             *pWidth = DVENCODER_WIDTH/2;
  1123.             if (DVENCODERVIDEOFORMAT_PAL == m_VideoFormat)
  1124.                 *pHeight = PAL_DVENCODER_HEIGHT/2;
  1125.             else if (DVENCODERVIDEOFORMAT_NTSC == m_VideoFormat)
  1126.                 *pHeight = NTSC_DVENCODER_HEIGHT/2;
  1127.             break;
  1128.  
  1129.         case DVRESOLUTION_QUARTER:
  1130.             *pWidth = DVENCODER_WIDTH/4;
  1131.             if (DVENCODERVIDEOFORMAT_PAL == m_VideoFormat)
  1132.                 *pHeight = PAL_DVENCODER_HEIGHT/4;
  1133.             else if (DVENCODERVIDEOFORMAT_NTSC == m_VideoFormat)
  1134.                 *pHeight = NTSC_DVENCODER_HEIGHT/4;
  1135.             break;
  1136.  
  1137.         case DVRESOLUTION_DC:
  1138.             *pWidth = 88;
  1139.             if (DVENCODERVIDEOFORMAT_PAL == m_VideoFormat)
  1140.                *pHeight = PAL_DVENCODER_HEIGHT/8;
  1141.             else if (DVENCODERVIDEOFORMAT_NTSC == m_VideoFormat)
  1142.                *pHeight = NTSC_DVENCODER_HEIGHT/8;
  1143.             break;
  1144.     }
  1145.  
  1146.     return hr;
  1147. }
  1148.  
  1149. /*-------------------------------------------------------------------------
  1150. Routine:      DV_SeekATN
  1151. Purpose:      ATN Seek function - uses GetTransportBasicParameters to send RAW AVC command 
  1152. Arguments:    None
  1153. Returns:      TRUE if successful
  1154. Notes:        This is Absolute Track Number Seek not TimeCode Seek but uses the timecode display as input
  1155. ------------------------------------------------------------------------*/
  1156. HRESULT CDVGraph::SeekATN(int iHr, int iMn, int iSc, int iFr)
  1157. {
  1158.     BOOL bStatus = FALSE;
  1159.     HRESULT hr = S_OK;
  1160.     ULONG ulTrackNumToSearch;
  1161.     long iCnt = 8;
  1162.  
  1163.     if (DVENCODERVIDEOFORMAT_PAL == m_VideoFormat && (iFr > 25) )
  1164.     {
  1165.         Dump(TEXT("Invalid Parameter - Frame should be less than 25 for PAL"));
  1166.         return E_FAIL;
  1167.     }
  1168.     
  1169.     if (DVENCODERVIDEOFORMAT_NTSC == m_VideoFormat && (iFr > 30) )
  1170.     {
  1171.         Dump(TEXT("Invalid Parameter - Frame should be less than 30 for NTSC"));
  1172.         return E_FAIL;
  1173.     }   
  1174.     
  1175.  
  1176.     // ATN Seek Raw AVC Command 
  1177.     BYTE RawAVCPkt[8] = {0x00, 0x20, 0x52, 0x20, 0xff, 0xff, 0xff, 0xff};
  1178.  
  1179.     if (( iHr < 26) && (iHr >= 0) && ( iMn < 60) &&(iMn >=0) && (iSc < 60))
  1180.     {
  1181.         //Calculate the ATN
  1182.         if (m_AvgTimePerFrame == 40) 
  1183.         {
  1184.             ulTrackNumToSearch = ((iMn * 60 + iSc) * 25 + iFr) * 12 * 2;
  1185.         } 
  1186.         else 
  1187.         {
  1188.             // Drop two frame every minutes
  1189.             ulTrackNumToSearch = ((iMn * 60 + iSc) * 30 + iFr - ((iMn - (iMn / 10)) * 2)) * 10 * 2;
  1190.         }
  1191.         // Update the Raw AVC Command query
  1192.         RawAVCPkt[4] = (BYTE)  (ulTrackNumToSearch & 0x000000ff);
  1193.         RawAVCPkt[5] = (BYTE) ((ulTrackNumToSearch & 0x0000ff00) >> 8);
  1194.         RawAVCPkt[6] = (BYTE) ((ulTrackNumToSearch & 0x00ff0000) >> 16);
  1195.         
  1196.         // RAW AVC Call
  1197.         hr = m_pIAMExtTransport->GetTransportBasicParameters(ED_RAW_EXT_DEV_CMD, &iCnt, (LPOLESTR *)RawAVCPkt);     
  1198.         if (ERROR_TIMEOUT == hr)
  1199.             OutputDebugString(TEXT(" ATN Seek returns ERROR_TIMEOUT"));
  1200.         else if (ERROR_REQ_NOT_ACCEP == hr)
  1201.             OutputDebugString(TEXT(" ATN Seek returns ERROR_REQ_NOT_ACCEP"));
  1202.         else if (ERROR_NOT_SUPPORTED == hr)
  1203.             OutputDebugString(TEXT(" ATN Seek returns ERROR_NOT_SUPPORTED"));
  1204.         else if (ERROR_REQUEST_ABORTED == hr)
  1205.             OutputDebugString(TEXT(" ATN Seek returns ERROR_REQUEST_ABORTED "));
  1206.         
  1207.     }
  1208.     else
  1209.     {
  1210.         Dump(TEXT("Invalid Parameter - Time entered should be:\nHour:Minute:Second:Frame"));
  1211.         hr = E_FAIL;
  1212.     } 
  1213.     return hr;
  1214.  
  1215.  
  1216.